package org.chen.wordwave.tools.token;

import org.chen.wordwave.base.Base64Util;

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

public class TokenUtils {
    private static final String RSA_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz93XIzimWfOzID0sMCz39s59TFwqbM7Q3L/t6JKY3MeoxtOInoruzc6PfblkkqdzoP6P/eLhk6dt4SEz/HlCX3JaqZqk8Nh+MMyD7rRWe1FXWkmseMqB2HqYW2b07KCyJcwg2tFQuwllmzIxtdM0Z1tgU7rKfw0utDNjpQa1avv3euagSCzvbmb8Qe49UkhDAbWf1OZDFMBZ56Mj1eaQv0s80LgbUlvMy87iujVE2sJyAklM2JtkK0VhHphMUPHW6GEr862iNC2Hm8YNraeubOXMJIgaaooml9O7rkltETU7MhjOm09ezpEt8c+P0hs27chlbi2LzS57GxDZwxmQTQIDAQAB";
    private static final String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";

    /**
     * encryption algorithm RSA
     */
    public static final String KEY_ALGORITHM = "RSA";

    /**
     * RSA Maximum Encrypted Plaintext Size
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    public static String encrypt(byte[] data)
            throws Exception {
        byte[] keyBytes = Base64Util.decode(RSA_PUBLIC_KEY);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // Sectional Encryption of Data
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();


        return Base64.getEncoder().encodeToString(encryptedData);
    }
}
